package com.dart.framework.aop;

import java.lang.reflect.Method;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dart.framework.annotations.Log;

/**
 * 日志切面处理类
 * Spring AOP 声明式配置：
 * <pre>
 * 	&lt;!-- 切面类 --&gt;
 *	&lt;bean id="logAspect" class="com.dart.framework.aop.LogAspect"&gt;
 *		&lt;property name="handler"&gt;
 *			&lt;bean class="日志处理接口的实现类" /&gt;
 *		&lt;/property&gt;
 *	&lt;/bean&gt;
 *	&lt;aop:config&gt;
 *		&lt;!-- 切面切入点 --&gt;
 *		&lt;aop:pointcut id="logPointCut" expression="@annotation(com.dart.framework.annotations.Log)"/&gt;
 *		
 *		&lt;aop:aspect ref="logAspect"&gt;
 *			&lt;!-- 执行方法前执行的切面方法 --&gt;
 *			&lt;aop:around pointcut-ref="logPointCut" method="saveLog" /&gt;
 *			&lt;!-- 异常后执行的切面方法 --&gt;
 *			&lt;aop:after-throwing pointcut-ref="logPointCut" method="throwLog" throwing="x" /&gt;
 *		&lt;/aop:aspect&gt;
 *	&lt;/aop:config&gt;
 * </pre>
 * @作者：杨浩泉
 * @日期：2016年9月28日
 */
public class LogAspect {
	
	private static Logger logger = LoggerFactory.getLogger(LogAspect.class) ;
	
	/**
	 * 日志处理接口
	 */
	private LogHandler handler ;
	
	public Object saveLog(ProceedingJoinPoint joinPoint) throws Throwable {
		/**
		 * 解析Log注解
		 */
		String methodName = joinPoint.getSignature().getName();
		Method method = currentMethod(joinPoint, methodName);
		Log log = method.getAnnotation(Log.class);
		
		/**
		 * 日志入库
		 */
		if (log != null) {
			if(handler != null) {
				handler.saveLog(joinPoint, methodName, (StringUtils.isBlank(log.value())?"操作未说明":log.value()));
			} else {
				logger.warn("日志处理接口类未实现");
			}
		}
		
		/**
		 * 方法执行
		 */
		return joinPoint.proceed();
	}
	
	public void thorwingLog(JoinPoint joinPoint, Throwable ex) {
		/**
		 * 解析Log注解
		 */
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = joinPoint.getSignature().getName();
		
        Log log = (Log) signature.getMethod().getAnnotation(Log.class);
        
        if(handler != null) {
			handler.thorwingLog(joinPoint, methodName, ex, (log != null ? log.value() : ""));
		} else {
			logger.warn("日志处理接口类未实现");
		}
        
	}
	
	
	
	/**
	 * 
	 * @param joinPoint 连接点
	 * @param methodName 方法名称
	 * @return 方法
	 */
	private Method currentMethod(ProceedingJoinPoint joinPoint, String methodName) {
		/**
		 * 获取目标类的所有方法，找到当前要执行的方法
		 */
		Method[] methods = joinPoint.getTarget().getClass().getMethods();
		Method resultMethod = null;
		for (Method method : methods) {
			if (method.getName().equals(methodName)) {
				resultMethod = method;
				break;
			}
		}
		return resultMethod;
	}

	public void setHandler(LogHandler handler) {
		this.handler = handler;
	}
}
